﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using DigitalImage.softLib.util;
using System.Drawing;

namespace DigitalImage.softLib.stages._5NeuralNetwork {
    class CNNbackPropagation:INeuralNetwork {
        private double[, ,] trainSet;
        private string trainMapper="";
        private CBackPropagation nn;
        private int[] dimenzijaSrednjihSlojeva;
        private int dimenzijaUlaza;

        public CNNbackPropagation(int dimenzijaUlaza,int[] dimenzijaSrednjihSlojeva) {
            this.dimenzijaUlaza=dimenzijaUlaza;
            this.dimenzijaSrednjihSlojeva = dimenzijaSrednjihSlojeva;
        }

        public void train(List<List<CRasterRegion>> regions, List<string> trainMapperRows) {
            createTrainmapper(trainMapperRows);

            int[] slojevi=new int[dimenzijaSrednjihSlojeva.Length+2];
            slojevi[0]=dimenzijaUlaza;
            dimenzijaSrednjihSlojeva.CopyTo(slojevi, 1);
            slojevi[slojevi.Length-1]=trainMapper.Length;

            //izbrisi prazna mesta
            for(int i=0;i<regions.Count;i++) {
                for(int j=0;j<regions[i].Count;j++) {
                    if(regions[i][j]==CRasterRegion.spaceRegion) {
                        regions[i].RemoveAt(j);
                        j--;
                    }
                }
            }

            int numberOfRegions=0;
            foreach(List<CRasterRegion> row in regions){
                foreach(CRasterRegion region in row){
                    numberOfRegions++;
                }
            }
            
            double[,,] obucavajuciSkup=new double[numberOfRegions,2,Math.Max(slojevi[0],slojevi[slojevi.Length-1])];

            double[] input;
            int brojUzorka=0;
            for(int i=0;i<regions.Count;i++){
                for(int j=0;j<regions[i].Count;j++){
                    input=CImageUtil.prepareForNN(regions[i][j].odrediSliku(),dimenzijaUlaza);
                    for(int k=0;k<dimenzijaUlaza;k++){
                        obucavajuciSkup[brojUzorka,0,k]=input[k];
                    }
                    char[] c=new char[1];
                    c[0]=trainMapperRows[i][j];
                    int index=trainMapper.IndexOfAny(c);
                    for(int k=0;k<slojevi[slojevi.Length-1];k++){
                        obucavajuciSkup[brojUzorka,1,k]=(k==index)?1:0;
                    }
                    brojUzorka++;
                }
            }

            nn=new CBackPropagation(obucavajuciSkup, slojevi);
            nn.obuci();
        }

        protected void createTrainmapper(List<string> trainMapperRows) {
            foreach (string s in trainMapperRows) {
                foreach (char c in s) {
                    if (!trainMapper.Contains(c)) {
                        trainMapper += c;
                    }
                }
            }
        }

        public char recognize(CRasterRegion region) {
            double[] output=nn.izracunaj(CImageUtil.prepareForNN(region.odrediSliku(),dimenzijaUlaza));
            double max=output[0];
            int maxIndex=0;
            for(int i=1;i<output.Length;i++) {
                if(output[i]>max) {
                    max=output[i];
                    maxIndex=i;
                }
            }
            return trainMapper[maxIndex];
        }

        public static string findAlphabet(string trainFilePath, string trainFileSeparator) {
            StreamReader inputFile = new StreamReader(trainFilePath, Encoding.UTF8);
            string newRow;
            string[] parts;
            string trainMapper = "";
            while (inputFile.Peek() != -1) {
                newRow = inputFile.ReadLine();
                parts = newRow.Split(trainFileSeparator.ToCharArray());
                for (int i = 0; i < parts.Length; i++) {
                    string currentWord=parts[i];
                    for (int j = 0; j < currentWord.Length; j++) {
                        if (!trainMapper.Contains(currentWord[j])) {
                            trainMapper += currentWord[j];
                        }
                    }
                    foreach (string s in parts) {
                        foreach (char c in s.ToCharArray()) {
                            
                        }
                    }
                }
            }
            return trainMapper.Replace(" ","");
        }

        public List<PointF> getErrors() {
            return nn.greske;
        }
    }
}
